package com.yk.i_wms.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yk.i_wms.common.model.CheckWarehouseEnum;
import com.yk.i_wms.common.model.Result;
import com.yk.i_wms.dto.SmsReceiveDocDTO;
import com.yk.i_wms.mapper.SmsReceiveDocMapper;
import com.yk.i_wms.model.*;
import com.yk.i_wms.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 入库单
 *
 * @author hbq
 * @date 2021-04-01 17:36:42
 */
@Slf4j
@Service
public class SmsReceiveDocServiceImpl extends ServiceImpl<SmsReceiveDocMapper, SmsReceiveDoc> implements ISmsReceiveDocService {
    @Resource
    private SmsReceiveDocMapper smsReceiveDocMapper;
    @Autowired
    private ISmsReceiveDocDetailService smsReceiveDocDetailService;
    @Autowired
    private ISmsBarcodeService smsBarcodeService;
    @Autowired
    private IUmsUserService umsUserService;
    @Autowired
    private ISmsStockInfoService smsStockInfoService;
    @Autowired
    private IUmsItemService umsItemService;
    /**
     * 列表
     * @param params
     * @return
     */
    public Page<Map> findList(Map<String, Object> params){
        Integer pageNum = MapUtils.getInteger(params, "pageNum");
        Integer pageSize = MapUtils.getInteger(params, "pageSize");
        if (pageNum == null) {
            pageNum = 1;
        }
        if (pageSize == null) {
            pageSize = -1;
        }
        Page<Map> pages = new Page<>(pageNum, pageSize);
        return smsReceiveDocMapper.findList(pages, params);
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result saveAll(SmsReceiveDocDTO smsReceiveDocDTO) {
        try{
            SmsReceiveDoc smsReceiveDoc=smsReceiveDocDTO;
            if (smsReceiveDoc.getDocState()!=1){
                return Result.failed("非新建状态不允许修改");
            }
            log.info("新建或更新入库单：{}",smsReceiveDocDTO);
            String docNo =StrUtil.isBlank(smsReceiveDocDTO.getDocNo())?getNewNo(smsReceiveDoc.getDocType()):smsReceiveDocDTO.getDocNo();
            smsReceiveDoc.setDocNo(docNo);
            //删除原有docNo的详情
            smsReceiveDocDetailService.remove(new LambdaQueryWrapper<SmsReceiveDocDetail>().eq(SmsReceiveDocDetail::getDocNo,docNo));
            List<SmsReceiveDocDetail> smsReceiveDocDetails = smsReceiveDocDTO.getSmsReceiveDocDetails();
            if (smsReceiveDocDetails == null||smsReceiveDocDetails.isEmpty()) {
                return Result.failed(  "详情列表不能为空");
            }
            smsReceiveDocDetails.forEach(u->{
                u.setDocNo(docNo);
            });
            saveOrUpdate(smsReceiveDoc);
            smsReceiveDocDetailService.saveBatch(smsReceiveDocDetails);
            return Result.succeed("保存成功");
        }
        catch (Exception e){
            // 事务回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.failed( e,"保存失败");
        }
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result delete(Map<String, List<Long>> map) {
        try{
            List<Long> ids = map.get("ids");
            for (Long id : ids) {
                SmsReceiveDoc receiveDoc = getById(id);
                if (receiveDoc.getDocState()!=1){
                    int i=1/0;
                }
                String docNo = receiveDoc.getDocNo();
                removeById(id);
                smsReceiveDocDetailService.remove(new LambdaQueryWrapper<SmsReceiveDocDetail>()
                        .eq(SmsReceiveDocDetail::getDocNo,docNo)
                );
            }
            return Result.succeed("删除成功");
        }
        catch (Exception e){
            // 事务回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.failed( e,"保存失败，单状态非新建");
        }
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result scanSN(Map<String, Object> map) {
        try{
            log.info("扫码入库请求参数{}",map);
            String sn = MapUtil.getStr(map, "sn");
            String createName = MapUtil.getStr(map, "createName");
            String docNo = MapUtil.getStr(map, "docNo");
            Integer docType = MapUtil.getInt(map, "docType");
            SmsBarcode barcode = smsBarcodeService.getOne(new LambdaQueryWrapper<SmsBarcode>().eq(SmsBarcode::getSn, sn));
            if (barcode == null) {
                return Result.failed("无此条码");
            }
            Long snNum = barcode.getSnNum();
            SmsReceiveDoc receiveDoc = getOne(new LambdaQueryWrapper<SmsReceiveDoc>().eq(SmsReceiveDoc::getDocNo, docNo));
            if (receiveDoc == null) {
                return Result.failed("无此单号");
            }
            if (!barcode.getDocNo().equals(receiveDoc.getDocNo())){
                return Result.failed("单号不符");
            }
/*            if (!receiveDoc.getDocType().equals(docType)){
                return Result.failed("类型不符");
            }*/
            SmsStockInfo stockInfo = smsStockInfoService.getOne(new LambdaQueryWrapper<SmsStockInfo>().eq(SmsStockInfo::getSn, sn));
            if (stockInfo != null) {
                return Result.failed("重复扫码");
            }
            SmsReceiveDocDetail docDetail = smsReceiveDocDetailService.getOne(new LambdaQueryWrapper<SmsReceiveDocDetail>()
                    .eq(SmsReceiveDocDetail::getDocNo, docNo)
                    .eq(SmsReceiveDocDetail::getPoNo, barcode.getPoNo())
                    .eq(SmsReceiveDocDetail::getItemCode, barcode.getItemCode())
                    .eq(SmsReceiveDocDetail::getBatch, barcode.getBatch())
            );
            if (docDetail == null) {
                return Result.failed("条码不符");
            }
            Long planQty = docDetail.getPlanQty();
            Long realQty = docDetail.getRealQty();
            Long remainTotal=planQty-realQty;
            if (remainTotal<snNum){
                return Result.failed("条码数量超出待收数量");
            }
            String itemCode = barcode.getItemCode();
            UmsItem item = umsItemService.getOne(new LambdaQueryWrapper<UmsItem>().eq(UmsItem::getItemCode, itemCode));
            if (item == null){
                return Result.failed("物料不存在");
            }
            //更新条码状态
            barcode.setSnState(1);
            smsBarcodeService.updateById(barcode);

            //更新入库单状态
            receiveDoc.setDocState(2);
            updateById(receiveDoc);

            //更新入库单详情数量
            docDetail.setRealQty(realQty+snNum);
            smsReceiveDocDetailService.updateById(docDetail);

            //添加库存信息
            SmsStockInfo newStockInfo = new SmsStockInfo();
            newStockInfo.setSn(sn);
            newStockInfo.setDocNo(docNo);
            newStockInfo.setItemCode(barcode.getItemCode());
            newStockInfo.setItemName(barcode.getItemName());
            newStockInfo.setBatch(barcode.getBatch());
            newStockInfo.setPdate(barcode.getPdate());
            newStockInfo.setTimeoutDate(DateUtil.offsetDay(barcode.getPdate(),item.getValidUntil()==null?730:item.getValidUntil()));
            newStockInfo.setQty(snNum);
            newStockInfo.setPoNo(barcode.getPoNo());
            newStockInfo.setWarehouse(docDetail.getCheckState()== CheckWarehouseEnum.S_1.getCheckState() ?CheckWarehouseEnum.S_1.getWarehouse():CheckWarehouseEnum.S_2.getWarehouse());
            newStockInfo.setWhCode(receiveDoc.getWhCode());
            newStockInfo.setCheckState(docDetail.getCheckState());
            newStockInfo.setSupplierCode(receiveDoc.getSupplierCode());
            newStockInfo.setInStockTime(new Date());
            newStockInfo.setInStockMan(createName);
            newStockInfo.setStockState(1);
            smsStockInfoService.save(newStockInfo);

            return Result.succeed("入库成功");
        }
        catch (Exception e){
            // 事务回滚
            log.error("扫码入库异常：",e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.failed( e,"保存失败，请联系管理员");
        }
    }

    @Override
    public Result close(SmsReceiveDoc smsReceiveDoc) {
        String docNo = smsReceiveDoc.getDocNo();
        int receiveDetailTotal = smsReceiveDocDetailService.count(new LambdaQueryWrapper<SmsReceiveDocDetail>().eq(SmsReceiveDocDetail::getDocNo, docNo));
        int receivedCount = smsReceiveDocDetailService.count(new LambdaQueryWrapper<SmsReceiveDocDetail>().eq(SmsReceiveDocDetail::getDocNo, docNo).last("and plan_qty=real_qty"));
        if (receiveDetailTotal!=receivedCount){
            return Result.failed("实收数量不符");
        }
        SmsReceiveDoc receiveDoc = getOne(new LambdaQueryWrapper<SmsReceiveDoc>().eq(SmsReceiveDoc::getDocNo, docNo));
        receiveDoc.setDocState(3);
        updateById(receiveDoc);
        return Result.succeed("关结成功");
    }

    /**
     * 获取新的串号
     * @return 当前串号的下一个串号
     */
    private String getNewNo(Integer docType){
        //生成新的串号
        String prefix="RE0"+ docType + DateUtil.format(new Date(), "yyyyMMdd");
        String maxNo=prefix+"001";
        SmsReceiveDoc one = getOne(new QueryWrapper<SmsReceiveDoc>()
                .last("where doc_no like '" + prefix + "%' order by doc_no desc limit 1"));
        if (one != null) {
            Long aLong = Convert.toLong(StrUtil.removePrefix(one.getDocNo(), prefix));
            maxNo=prefix+String.format("%3d",aLong+1).replace(" ","0");
        }
        return maxNo;
    }
}
